package com.android.adc.service;

import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.hardware.SensorManager;
import android.media.AudioManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

import com.android.adc.VolumeManager;
import com.android.adc.sensors.SensorInformationManager;

public class RingManipulatorService extends Service implements IRingManipulatorService
{
	private static int loopDelay = 3000;
	private String MUSIC_AFFECTED_PREFERENCE_NAME = "MusicAffeced";
	private String HIGH_VOLUME_LEVEL_PREFERENCE_NAME = "HighVolume";
	private String LOW_VOLUME_LEVEL_PREFERENCE_NAME = "LowVolume";
	
	private Messenger serviceMessanger;
	
	private boolean started = false;
	private SensorInformationManager sensorManager;
	private VolumeManager audioManager;
	
	private Handler handler;
	private Worker worker;
	
	private boolean initialized = false;
	private int lastChangedCounter = 0;
	
	private SharedPreferences preferences;
	
	public int onStartCommand(Intent intent, int flags, int startId) 
	{
		Log.d( "ServiceDebug", "onStartCommand" );
		
		if(!initialized)
		{
			initialized = true;
			init();
		}
	
		startSampling();
		
		return START_NOT_STICKY;
	}
	
	private void init()
	{
		sensorManager = new SensorInformationManager((SensorManager)getSystemService(SENSOR_SERVICE));
		audioManager = new VolumeManager((AudioManager)getSystemService(AUDIO_SERVICE));
		serviceMessanger = new Messenger(new IncomingHandler());
		
		preferences = getSharedPreferences("RMS_Preferences", MODE_PRIVATE);

		audioManager.setLowVolume(preferences.getInt(LOW_VOLUME_LEVEL_PREFERENCE_NAME, audioManager.getDefaultVolume()));
		audioManager.setHighVolume(preferences.getInt(HIGH_VOLUME_LEVEL_PREFERENCE_NAME, 8));
		audioManager.setMusicAffected(preferences.getBoolean(MUSIC_AFFECTED_PREFERENCE_NAME, false));	
	}

	public IBinder onBind(Intent arg0) 
	{
		if(!initialized)
		{
			initialized = true;
			init();
		}
		
		if(!started)
			startSampling();
		
		return serviceMessanger.getBinder();
	}
	
	
	@Override
	public void onDestroy() 
	{
		started = false;
		
		if(sensorManager != null)
			sensorManager.unregister();
		
		audioManager.restoreVolume();
		
		super.onDestroy();
	}

	private void startSampling() 
	{
		if( started )
			return;
		
		worker = new Worker();
		handler = new Handler();
		
		handler.postDelayed(worker, loopDelay);
		

		started = true;
	}
	
	private class IncomingHandler extends Handler 
	{
        @Override
        public void handleMessage(Message msg) 
        {
            switch (msg.what) 
            {
                case SET_MUSIC_AFFECTED:
                {
                	Boolean value = (Boolean)msg.obj;
                	setVolumeAffected(value);
                    break;
                }
                case GET_VALUES:
                {
                	ServiceValues serivceValues = new ServiceValues();
                	serivceValues.setMusicAffected(isVolumeAffected());
                	serivceValues.setLowVolume(getLowVolume());
                	serivceValues.setHighVolume(getHighVolume());
                	serivceValues.setMaxValue(getMaxVolumeValue());
                	
                	Message message = Message.obtain(null,
                			GET_VALUES, serivceValues);
                	
                	sendMessageTo(msg.replyTo, message);
                	break;
                }
                case SET_LOW_VOLUME_VALUE:
                {
                	int volumeValue = (Integer)msg.obj;
                	setLowVolume(volumeValue);
                	
                	break;
                }
                case SET_HIGH_VOLUME_VALUE:
                {
                	int volumeValue = (Integer)msg.obj;
                	setHightVolume(volumeValue);
                	
                	break;
                }
                
                default:
                {
                    super.handleMessage(msg);
                }
            }
        }
    }
	
	private class Worker implements Runnable
	{
		@Override
		public void run() 
		{
			if( !started )
				return;
			
			int delay = loopDelay;
			
			if(sensorManager.hasChanged())
			{
				lastChangedCounter = 0;
				
				boolean volumeUp = sensorManager.isInMove();
				sensorManager.clearSensorAnalysis();
				
				audioManager.changeVolume(volumeUp);
			}
			else
			{
				/* Maksymalny zakres to 30, potem uznajemy, że to już maksimum */
				if(lastChangedCounter < 30)
					lastChangedCounter++;
				
				if(lastChangedCounter > 20)
					delay *= 4;
				else if(lastChangedCounter > 5)
					delay *= 2;
			}
			
			handler.postDelayed(worker, delay);
			

		}
		
	}
	
    private void sendMessageTo(Messenger messanger, Message message)
    {
		try 
		{
			messanger.send(message);
        } 
		catch (RemoteException e) 
        {

        }
    }

	@Override
	public void setVolumeAffected(boolean volumeAffected) 
	{
		/* Zapisz dane aplikacji do pliku konfiguracyjnego */
		Editor editor = preferences.edit();
		editor.putBoolean(MUSIC_AFFECTED_PREFERENCE_NAME, volumeAffected);
		editor.commit();
		
		audioManager.setMusicAffected(volumeAffected);
	}

	@Override
	public void setLowVolume(int value) 
	{
		/* Zapisz dane aplikacji do pliku konfiguracyjnego */
		Editor editor = preferences.edit();
		editor.putInt(LOW_VOLUME_LEVEL_PREFERENCE_NAME, value);
		editor.commit();
		
		audioManager.setLowVolume(value);
	}

	@Override
	public void setHightVolume(int value) 
	{
		/* Zapisz dane aplikacji do pliku konfiguracyjnego */
		Editor editor = preferences.edit();
		editor.putInt(HIGH_VOLUME_LEVEL_PREFERENCE_NAME, value);
		editor.commit();
		
		audioManager.setHighVolume(value);
	}

	@Override
	public boolean isVolumeAffected() {
		return audioManager.isVolumeAffected();
	}

	@Override
	public int getLowVolume() {
		return audioManager.getLowVolume();
	}

	@Override
	public int getHighVolume() {
		return audioManager.getHighVolume();
	}
	
	private int getMaxVolumeValue() {
		return audioManager.getMaxVolumeValue();
	}
	

}
